# -*- coding: utf-8 -*-

from __future__ import with_statement

from google.appengine.ext import db
from dicthash.for_testing import TestGoogleDataStore, in_namespace

from user.code.backends.working.models import User
from user.code.backends.working.exception import \
        UserNameDuplicateError, OneUserPerOpenidError, UserNameInvalidError
        
from user.code.backends.working import models
models.USER_NAME_VALIDATOR = lambda name: True        


class TestDbBase(TestGoogleDataStore):
    """ """
    pass


class TestNew(TestDbBase):
    """ """
    def test(self):
        """ """
        user = User.new('eblan4eg', 'eblan4eg@gmail.com')
        
        self.assertEqual(user.name, 'eblan4eg')
        self.assertEqual(user.openid, 'eblan4eg@gmail.com')
    
    
class TestPut(TestDbBase):
    """ """
    def test_put_in_transaction_new(self):
        """
        1. create new `User` instance
        2. save it
        """
        user = User.new('eblan4eg', 'eblan4eg@gmail.com')
        
        self.assertEqual(len(User.all().fetch(2)), 0)
        
        k = user.put()
        from_db = db.get(k)
        
        self.assertEqual(len(User.all().fetch(2)), 1)
        self.assertEqual(from_db.name, user.name)
        self.assertEqual(from_db.openid, user.openid)
        
    def test_put_in_transaction_dup_name(self):
        """
        1. create `User` instance and save it
        2. try to create another user with the same name
        3. check for error
        """
        user = User.new('eblan4eg', 'eblan4eg@gmail.com')
        user.put()
        
        user2 = User.new('eblan4eg', 'foo@boo.com')
        try:
            user2.put()
        except UserNameDuplicateError:
            pass
        
    def test_put_in_transaction_second_user_per_openid(self):
        """
        1. create `User` instance and save it
        2. try to create another user with the same openID
        3. check for error
        """
        user = User.new('eblan4eg', 'eblan4eg@gmail.com')
        user.put()
        
        self.assertEqual(len(User.all().fetch(20)), 1)
        
        user2 = User.new('foo', 'eblan4eg@gmail.com')
        try:
            user2.put()
        except OneUserPerOpenidError:
            pass
        else:
            self.assertTrue(False)
        
        self.assertEqual(len(User.all().fetch(20)), 1)
        
    def test_put_in_transaction_invalid_name(self):
        """
        """
        models.USER_NAME_VALIDATOR = lambda name: name != 'invalid'
        
        user = User.new('invalid', 'eblan4eg@gmail.com')
        try:
            user.put()
        except UserNameInvalidError:
            pass
        
        
class TestGetByOpenid(TestDbBase):
    """ """
    def test(self):
        """
        """
        user = User.new('eblan4eg', 'eblan4eg@gmail.com')
        user.put()
        
        from_db = User.get_by_openid('eblan4eg@gmail.com')
        
        self.assertTrue(from_db is not None)
        
    def test_namespaces(self):
        """
        1. add user under ""-namespace
        2. set namespace to user's name
        3. call get_by_openid classmethod
        """
        with in_namespace(''):
            user = User.new('eblan4eg', 'eblan4eg@gmail.com')
            user.put()
        with in_namespace('eblan4eg'):
            from_db = User.get_by_openid('eblan4eg@gmail.com')
            self.assertEqual(from_db.name, 'eblan4eg')    
        
        
class TestGetByName(TestDbBase):
    """ """
    def test_namespaces(self):
        """
        1. add user under ""-namespace
        2. set namespace to user's name
        3. call get_by_name classmethod
        """
        with in_namespace(''):
            user = User.new('eblan4eg', 'eblan4eg@gmail.com')
            user.put()
        with in_namespace('eblan4eg'):
            from_db = User.get_by_name('eblan4eg')
            self.assertEqual(from_db.name, 'eblan4eg')   